package com.culturalCenter.dataCenter.schedule.site;

import cn.hutool.core.date.DateUtil;
import com.culturalCenter.dataCenter.Utils.DateFormatUtil;
import com.culturalCenter.dataCenter.Utils.RedisUtil;
import com.culturalCenter.dataCenter.entity.site.SiteBooking;
import com.culturalCenter.dataCenter.entity.site.SiteUsedCount;
import com.culturalCenter.dataCenter.mapper.site.SiteAlertsMapper;
import com.culturalCenter.dataCenter.mapper.site.SiteBookingMapper;
import com.culturalCenter.dataCenter.mapper.site.SiteUsedCountMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 定时任务_场地_统计
 *
 * @author 方治森
 * @since 2022/4/20
 */
@Component
@Slf4j
@Async("dataThreadExecutor")
public class SiteDataStatistics {

    @Resource
    private SiteBookingMapper siteBookingMapper;
    @Resource
    private SiteAlertsMapper siteAlertsMapper;
    @Resource
    private SiteUsedCountMapper siteUsedCountMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private RedissonClient redisson;
    private Date beginTime;
    private Date endTime;
    private int year;
    private int month;

    /**
     * for test
     */
    // @PostConstruct
    public void initLock() {
        for (int i = 1; i <= 2; i++) {
            redisUtil.del("siteStatistics_lock" + i);
        }
    }

    /**
     * 场地使用情况(cdc_site_used_count)
     */
//    @Scheduled(cron = "${cron.siteStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void countSiteUsedByDays() {
        String lockKey = "siteStatistics_lock1";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            LocalDateTime localDateTime = LocalDateTime.now();
            ZoneId zoneId = ZoneId.systemDefault();

            // 近七天
            siteUsedCountMapper.deleteRecent();
            beginTime = Date.from(localDateTime.plusDays(-7).atZone(zoneId).toInstant());
            endTime = Date.from(localDateTime.atZone(zoneId).toInstant());
            List<SiteUsedCount> dataList = siteBookingMapper.countSiteUsedByDays(beginTime, endTime);
            if (CollectionUtils.isNotEmpty(dataList)) {
                dataList.forEach(data -> {
                    data.setYear(localDateTime.getYear());
                    data.setMonth(-1);
                    data.setTotal(7);
                    data.setUnusedDays(7 - siteBookingMapper.countUsedDays(data.getSiteId(), beginTime, endTime));
                    data.setAlertsNum(siteAlertsMapper.countAlertsNumBySiteId(data.getSiteId(), beginTime, endTime));
                });
                siteUsedCountMapper.insertBatch(dataList);
            }
            // 本月
            beginTime = DateFormatUtil.parse(localDateTime.getYear() + "-" + localDateTime.getMonth().getValue() + "-01");
            endTime = Date.from(localDateTime.atZone(zoneId).toInstant());
            dataList = siteBookingMapper.countSiteUsedByDays(beginTime, endTime);
            if (CollectionUtils.isNotEmpty(dataList)) {
                dataList.forEach(data -> {
                    data.setYear(localDateTime.getYear());
                    data.setMonth(localDateTime.getMonth().getValue());
                    int total = DateUtil.dayOfMonth(DateUtil.date());
                    data.setTotal(total);
                    data.setUnusedDays(total - siteBookingMapper.countUsedDays(data.getSiteId(), beginTime, endTime));
                    data.setAlertsNum(siteAlertsMapper.countAlertsNumBySiteId(data.getSiteId(), beginTime, endTime));
                });
                siteUsedCountMapper.insertBatch(dataList);
            }
            // 全年总的（三年，前年+去年+今年）
            for (int i = 0; i < 3; i++) {
                int year = localDateTime.getYear() - i;
                beginTime = DateFormatUtil.parse(year + "-01-01");
                endTime = (i == 0) ? Date.from(localDateTime.atZone(zoneId).toInstant()) : DateFormatUtil.parse(year + "-12-31");
                dataList = siteBookingMapper.countSiteUsedByDays(beginTime, endTime);
                if (CollectionUtils.isNotEmpty(dataList)) {
                    for (SiteUsedCount data : dataList) {
                        data.setYear(year);
                        data.setMonth(0);
                        Calendar cal = Calendar.getInstance();
                        cal.set(Calendar.YEAR, year);
                        int total = (i == 0) ? DateUtil.dayOfYear(DateUtil.date()) : cal.getActualMaximum(Calendar.DAY_OF_YEAR);
                        data.setTotal(total);
                        data.setUnusedDays(total - siteBookingMapper.countUsedDays(data.getSiteId(), beginTime, endTime));
                        data.setAlertsNum(siteAlertsMapper.countAlertsNumBySiteId(data.getSiteId(), beginTime, endTime));
                    }
                    siteUsedCountMapper.insertBatch(dataList);
                }
            }
            // 每年每月的（三年，前年+去年+今年）
            for (int y = 0; y < 3; y++) {
                year = localDateTime.getYear() - y;
                month = localDateTime.getMonth().getValue();
                // 本年
                if (y == 0) {
                    for (int m = 1; m <= month; m++) {
                        beginTime = DateFormatUtil.parse(year + "-" + m + "-01");
                        endTime = DateFormatUtil.parse(year + "-" + m + "-31");
                        dataList = siteBookingMapper.countSiteUsedByDays(beginTime, endTime);
                        if (CollectionUtils.isNotEmpty(dataList)) {
                            for (SiteUsedCount data : dataList) {
                                data.setYear(year);
                                data.setMonth(m);
                                YearMonth yearMonthObject = YearMonth.of(year, m);
                                int total = (m == month) ? DateUtil.dayOfMonth(DateUtil.date()) : yearMonthObject.lengthOfMonth();
                                data.setTotal(total);
                                data.setUnusedDays(total - siteBookingMapper.countUsedDays(data.getSiteId(), beginTime, endTime));
                                data.setAlertsNum(siteAlertsMapper.countAlertsNumBySiteId(data.getSiteId(), beginTime, endTime));
                            }
                            siteUsedCountMapper.insertBatch(dataList);
                        }
                    }
                }
                // 去年+前年
                else {
                    for (int m = 1; m <= 12; m++) {
                        beginTime = DateFormatUtil.parse(year + "-" + m + "-01");
                        endTime = DateFormatUtil.parse(year + "-" + m + "-31");
                        dataList = siteBookingMapper.countSiteUsedByDays(beginTime, endTime);
                        if (CollectionUtils.isNotEmpty(dataList)) {
                            for (SiteUsedCount data : dataList) {
                                data.setYear(year);
                                data.setMonth(m);
                                YearMonth yearMonthObject = YearMonth.of(year, m);
                                int total = yearMonthObject.lengthOfMonth();
                                data.setTotal(total);
                                data.setUnusedDays(total - siteBookingMapper.countUsedDays(data.getSiteId(), beginTime, endTime));
                                data.setAlertsNum(siteAlertsMapper.countAlertsNumBySiteId(data.getSiteId(), beginTime, endTime));
                            }
                            siteUsedCountMapper.insertBatch(dataList);
                        }
                    }
                }
            }

            log.info("============场地使用情况表更新完毕===========");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

    /**
     * 更新预约状态(cdc_site_booking的status)：status=5到了开始时间的更新为3，status=3到了结束时间的更新为4
     */
//    @Scheduled(cron = "${cron.siteStatistics}")
    // @Scheduled(cron = "${cron.test}")
    public void updateBookingStatus() {
        String lockKey = "siteStatistics_lock2";
        RLock redissonLock = redisson.getLock(lockKey);
        try {
            boolean locked = redissonLock.isLocked();
            if (!locked){
                redissonLock.lock();
            }
            List<SiteBooking> siteBookingList = siteBookingMapper.selectTodayBookings();
            siteBookingList.forEach(siteBooking -> {
                if (siteBooking.getStatus() == 5 && siteBooking.getBeginTime().before(new Date())) {
                    siteBooking.setStatus(3);
                }
                if (siteBooking.getStatus() == 3 && siteBooking.getEndTime().before(new Date())) {
                    siteBooking.setStatus(4);
                }
                siteBooking.setUpdateTime(new Date());
                siteBookingMapper.updateStatus(siteBooking);
            });

            log.info("============booking的status更新完毕===========");
        } finally {
            boolean locked = redissonLock.isLocked();
            if (locked){
                redissonLock.unlock();
            }
        }
    }

}
